package brand

import (
	"context"
	tools "mall/common/utils"
	constans "mall/services/product/rpc/consts"
	"mall/services/product/rpc/internal/domain/bo"
	"mall/services/product/rpc/internal/domain/do"
	"mall/services/product/rpc/internal/mapper"
	"mall/services/product/rpc/internal/mapper/entity"

	"mall/services/product/rpc/internal/svc"
	"mall/services/product/rpc/pb"

	"github.com/zeromicro/go-zero/core/logx"
)

type ListPageLogic struct {
	ctx    context.Context
	svcCtx *svc.ServiceContext
	logx.Logger
}

func NewBrandListPageLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ListPageLogic {
	return &ListPageLogic{
		ctx:    ctx,
		svcCtx: svcCtx,
		Logger: logx.WithContext(ctx),
	}
}

func (l *ListPageLogic) BrandListPage(in *pb.BrandListPageDTO) (*pb.BrandListPageVO, error) {
	// 1.select count
	brandMapper, totalCount, selectErr := l.selectCount(in)
	if selectErr != nil {
		return nil, selectErr
	}
	// 1.1 if select count <= 0 return empty lis
	if totalCount <= 0 {
		return &pb.BrandListPageVO{PageSize: in.PageSize, CurrentPage: in.PageNum}, nil
	}
	// 2.select page list
	brandEntityArr, selectPageErr := l.selectBrandPageList(in, brandMapper)
	if selectPageErr != nil {
		return nil, selectPageErr
	}
	// 3.select category info
	m, selectCategoryErr := l.selectCategory(brandEntityArr)
	if selectCategoryErr != nil {
		return nil, selectCategoryErr
	}
	// 4.package info
	return l.packageObj(in, totalCount, brandEntityArr, m), nil
}

func (l *ListPageLogic) packageObj(in *pb.BrandListPageDTO, totalCount int64, brandEntityArr []entity.BrandEntity,
	m map[int64]do.CategoryDO) *pb.BrandListPageVO {

	resp := new(pb.BrandListPageVO)
	pageUtil := tools.NewPageUtil[entity.BrandEntity](in.PageNum, in.PageNum, int32(totalCount), brandEntityArr)
	resp.TotalPage = pageUtil.TotalPage
	resp.HasNextPage = pageUtil.HasNextPage
	resp.CurrentPage = pageUtil.CurrentPage
	resp.TotalCount = pageUtil.TotalCount
	resp.Prev = pageUtil.Prev
	resp.PageSize = in.PageSize
	resp.Next = pageUtil.Next
	records := pageUtil.Records
	var respRecords []*pb.BrandInfoVO
	for _, v := range records {
		vo := new(pb.BrandInfoVO)
		vo.BrandId = v.BrandId
		vo.CreateTime = v.CreateTime.Format("2006-01-02 15:04:05")
		vo.UpdateTime = v.UpdateTime.Format("2006-01-02 15:04:05")
		vo.Name = v.Name
		vo.Desc = v.Desc
		vo.ImgUrl = v.ImgUrl
		vo.FirstLetter = v.FirstLetter
		vo.Seq = int32(v.Seq)
		vo.Status = int32(v.Status)
		categoryDO := m[v.BrandId]
		if categoryDO.CategoryId > 0 {
			categoryVo := new(pb.CategoryVO)
			categoryVo.CategoryId = categoryDO.CategoryId
			categoryVo.ShopId = categoryDO.ShopId
			categoryVo.ParentId = categoryDO.ParentId
			categoryVo.Name = categoryDO.Name
			categoryVo.Desc = categoryDO.Desc
			categoryVo.Path = categoryDO.Path
			categoryVo.Status = int32(categoryDO.Status)
			categoryVo.Icon = categoryDO.Icon
			categoryVo.ImgUrl = categoryDO.ImgUrl
			categoryVo.Level = int32(categoryDO.Level)
			categoryVo.Status = int32(categoryDO.Status)
			vo.Category = categoryVo
		}
		respRecords = append(respRecords, vo)
	}
	resp.Records = respRecords
	return resp
}

func (l *ListPageLogic) selectCategory(brandEntityArr []entity.BrandEntity) (map[int64]do.CategoryDO, error) {
	var brandIdArr []int64
	for _, v := range brandEntityArr {
		brandIdArr = append(brandIdArr, v.BrandId)
	}
	categoryBrandMapper := mapper.NewCategoryBrandMapper(l.ctx)
	doArr, err := categoryBrandMapper.SelectCategoryCtx(l.svcCtx.DBEngin, brandIdArr)
	if err != nil {
		return nil, err
	}
	m := make(map[int64]do.CategoryDO)
	for _, v := range doArr {
		m[v.BrandId] = v
	}
	return m, nil
}

func (l *ListPageLogic) selectBrandPageList(in *pb.BrandListPageDTO,
	brandMapper *mapper.BrandMapper) ([]entity.BrandEntity, error) {

	pageNum := in.PageNum
	pageSize := in.PageSize
	startPageIndex := 0
	if pageNum > 1 {
		startPageIndex = int((pageNum - 1) * pageSize)
	}
	brandBO := bo.BrandBO{}
	brandBO.NameAllLike = in.Name
	brandBO.FirstLetter = in.FirstLetter
	brandBO.StartTime = in.StartTime
	brandBO.EndTime = in.EndTime
	brandBO.StartIndex = startPageIndex
	brandBO.PageSize = int(pageSize)
	// default sorts
	orderBO := bo.OrderBO{}
	orderBO.FiledName = "update_time"
	orderBO.Sort = "desc"
	var sortBOArr []bo.OrderBO
	sortBOArr = append(sortBOArr, orderBO)
	sortBOArr = append(sortBOArr, bo.OrderBO{
		FiledName: "create_time",
		Sort:      "desc",
	})
	brandBO.Sorts = sortBOArr
	brandBO.NeStatus = constans.Delete
	return brandMapper.SelectPageListCtx(l.svcCtx.DBEngin, brandBO)
}

func (l *ListPageLogic) selectCount(in *pb.BrandListPageDTO) (*mapper.BrandMapper, int64, error) {
	brandMapper := mapper.NewBrandMapper(l.ctx)
	brandBO := bo.BrandBO{}
	brandBO.NameAllLike = in.Name
	brandBO.FirstLetter = in.FirstLetter
	brandBO.StartTime = in.StartTime
	brandBO.EndTime = in.EndTime
	brandBO.NeStatus = constans.Delete
	selectCountCtx, err := brandMapper.SelectCountCtx(l.svcCtx.DBEngin, brandBO)
	return brandMapper, selectCountCtx, err
}
